import { symlinkCommon } from "./Utils"
import { Connection, MyServer } from "./Core"
import {
    ApiMsgEnum,
    IApiPlayerJoinReq,
    IApiPlayerJoinRes,
    IApiPlayerListReq,
    IApiPlayerListRes,
    IApiRoomCreateReq,
    IApiRoomCreateRes,
    IApiRoomJoinReq,
    IApiRoomJoinRes,
    IApiRoomLeaveReq,
    IApiRoomLeaveRes,
    IApiRoomListReq,
    IApiRoomListRes,
    IApiGameStartReq,
    IApiGameStartRes,
} from "./Common"
import { PlayerManager } from "./Biz/PlayerManager"
import { RoomManager } from "./Biz/RoomManager"
import { Room } from "./Biz/Room"

symlinkCommon()

declare module "./Core" { // 扩展 Connection，添加 playerId 字段，不直接在 Connection 上添加，避免业务代码污染原有代码
    interface Connection {
        playerId: number // 连接对应的玩家ID
    }
}

const server = new MyServer({
    port: 9876
})

server.on("connection", (connection: Connection) => {
    console.log("来人了: ", server.connections.size)
})

server.on("disconnection", (connection: Connection) => {
    console.log("走人了: ", server.connections.size)
    if (connection.playerId) {
        // 断开连接时删除 Player
        PlayerManager.Instance.removePlayer(connection.playerId)
        // 有玩家断线，同步一份玩家列表给所有人
        PlayerManager.Instance.syncPlayers()
    }
    console.log("PlayerManager.Instance.players.size: ", PlayerManager.Instance.players.size)
})

// 玩家登录接口
server.setApi(ApiMsgEnum.ApiPlayerJoin, (connection: Connection, data: IApiPlayerJoinReq): IApiPlayerJoinRes => {
    const player = PlayerManager.Instance.createPlayer({
        nickname: data.nickname,
        connection
    })
    connection.playerId = player.id
    // 有新玩家登录，同步一份玩家列表给所有人
    PlayerManager.Instance.syncPlayers()
    return {
        player: PlayerManager.Instance.getPlayerView(player),
    }
})

// 获取玩家列表接口
server.setApi(ApiMsgEnum.ApiPlayerList, (connection: Connection, data: IApiPlayerListReq): IApiPlayerListRes => {
    return {
        list: PlayerManager.Instance.getPlayersView(),
    }
})

// 房间列表接口
server.setApi(ApiMsgEnum.ApiRoomList, (connection: Connection, data: IApiRoomListReq): IApiRoomListRes => {
    return {
        list: RoomManager.Instance.getRoomsView(),
    }
})

// 房间创建接口
server.setApi(ApiMsgEnum.ApiRoomCreate, (connection: Connection, data: IApiRoomCreateReq): IApiRoomCreateRes => {
    if (connection.playerId) {
        const newRoom = RoomManager.Instance.createRoom()
        const room = RoomManager.Instance.joinRoom(newRoom.id, connection.playerId)
        if (room) {
            // PlayerManager.Instance.syncPlayers() // 创建房间感觉不需要同步玩家列表
            RoomManager.Instance.syncRooms()
            return {
                room: RoomManager.Instance.getRoomView(room)
            }
        } else {
            throw new Error("房间不存在")
        }
    } else {
        throw new Error("未登录")
    }
})

// 加入房间接口
server.setApi(ApiMsgEnum.ApiRoomJoin, (connection: Connection, data: IApiRoomJoinReq): IApiRoomJoinRes => {
    if (connection.playerId) {
        const rid = data.rid
        const room = RoomManager.Instance.joinRoom(rid, connection.playerId)
        if (room) {
            // PlayerManager.Instance.syncPlayers() // 加入房间感觉不需要同步玩家列表
            // RoomManager.Instance.syncRooms() // 加入房间感觉不需要同步房间列表
            RoomManager.Instance.syncRoom(rid) // 告诉这个房间里的其他人有新玩家进入
            return {
                room: RoomManager.Instance.getRoomView(room)
            }
        } else {
            throw new Error("房间不存在")
        }
    } else {
        throw new Error("未登录")
    }
})

// 离开房间接口
server.setApi(ApiMsgEnum.ApiRoomLeave, (connection: Connection, data: IApiRoomLeaveReq): IApiRoomLeaveRes => {
    if (!connection.playerId) {
        throw new Error("未登录")
    }

    const player = PlayerManager.Instance.idMapPlayer.get(connection.playerId)
    if (!player) {
        throw new Error("玩家不存在")
    }

    const rid = player.rid
    if (!rid) {
        throw new Error("玩家不在任何房间内")
    }

    RoomManager.Instance.leaveRoom(rid, connection.playerId)
    RoomManager.Instance.syncRoom(rid)
    // 玩家离开房间后房间可能销毁，此时有必要同步一下房间列表给所有人
    RoomManager.Instance.syncRooms()
    return {}
})

// 游戏开始接口
server.setApi(ApiMsgEnum.ApiGameStart, (connection: Connection, data: IApiGameStartReq): IApiGameStartRes => {
    if (!connection.playerId) {
        throw new Error("未登录")
    }

    const player = PlayerManager.Instance.idMapPlayer.get(connection.playerId)
    if (!player) {
        throw new Error("玩家不存在")
    }

    const rid = player.rid
    if (!rid) {
        throw new Error("玩家不在任何房间内")
    }

    RoomManager.Instance.startRoom(rid)

    return {}
})

server.start().then(() => {
    console.log("服务启动成功！")
}).catch((e) => {
    console.error("服务启动失败：", e)
})

/* 
const wss = new WebSocketServer({ port: 9876 })

let inputs = []

wss.on("connection", (socket) => {
    socket.on("message", (buffer) => {
        const str = buffer.toString()
        try {
            const msg = JSON.parse(str)
            const { name, data } = msg
            const { frameId, input } = data
            inputs.push(input) // 并不直接发送每一份数据，先存起来
        } catch (error) {
            console.log(error)
        }
    })

    // 每隔100毫秒批量发送一次数据
    setInterval(() => {
        const temp = inputs
        inputs = []
        const msg = {
            name: ApiMsgEnum.MsgServerSync,
            data: {
                inputs: temp,
            }
        }
        socket.send(JSON.stringify(msg))
    }, 100)

    // 2 秒后再发送一条测试消息给客户端
    setTimeout(() => {
        const obj = {
            name: "haha",
            data: "haha123",
        }
        socket.send(JSON.stringify(obj))
    }, 2000)
})

wss.on("listening", () => {
    console.log("服务启动!")
})
*/